//The MIT License (MIT)
//
//Copyright (c) 2020 lihp1603
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in
//all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//THE SOFTWARE.

package monitor

import (
	"gitee.com/lihaiping1603/monitor/proc"
	"syscall"
	"time"
)

type SelfStats struct {
	rusage          syscall.Rusage
	sysMemTotal     uint64    //记录内存的总大小
	Pid             int       `json:"pid"`
	PPid            int       `json:"ppid"`
	MemKByte        uint64    `json:"mem_kbyte"`
	MemPercent      float64   `json:"mem_percent"`
	CpuUsagePercent float64   `json:"cpu_percent"`
	SampleTime      time.Time `json:"sample_time"`
}

func NewSelfStats() (*SelfStats, error) {
	self := &SelfStats{Pid: syscall.Getpid(), PPid: syscall.Getppid()}
	//获取一下系统的内存
	sys_mem_info, err := proc.ReadMemInfo()
	if err != nil {
		return nil, err
	}
	self.sysMemTotal = sys_mem_info.GetMemTotalKB()
	if err := self.UpdateMonitorInfo(); err != nil {
		return nil, err
	}
	return self, nil
}

func (self *SelfStats) UpdateMonitorInfo() error {
	last_rusage := self.rusage
	last_sample_time := self.SampleTime
	if err := syscall.Getrusage(syscall.RUSAGE_SELF, &self.rusage); err != nil {
		return err
	}
	self.MemKByte = uint64(self.rusage.Maxrss)
	self.SampleTime = time.Now()
	//计算内存占比
	if self.sysMemTotal > 0 && self.MemKByte > 0 {
		self.MemPercent = 100.0 * float64(self.MemKByte) / float64(self.sysMemTotal)
	}
	//微秒
	last_user_time := last_rusage.Utime.Sec*1000000000 + last_rusage.Utime.Usec
	last_kernel_time := last_rusage.Stime.Sec*1000000000 + last_rusage.Stime.Usec
	last_cpu_time := last_user_time + last_kernel_time
	if last_cpu_time > 0 {
		cur_rusage := self.rusage
		user_time := cur_rusage.Utime.Sec*1000000000 + cur_rusage.Utime.Usec
		kernel_time := cur_rusage.Stime.Sec*1000000000 + cur_rusage.Stime.Usec
		cur_cpu_time := user_time + kernel_time

		cur_sample_time := self.SampleTime
		intval_time := cur_sample_time.Sub(last_sample_time).Microseconds()

		//计算cpu使用率
		if intval_time > 0 {
			cpu_usage_percent := 100.0 * float64(cur_cpu_time-last_cpu_time) / float64(intval_time)
			self.CpuUsagePercent = cpu_usage_percent
		}
	}
	return nil
}
